package com.jvyou.mybatis.executor.resultset;

import com.jvyou.mybatis.utils.string.StringUtils;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 橘柚
 * @version 1.0-SNAPSHOT
 * @Date 2024/7/23 13:39
 * @Description 元数据解析器
 */
public class TableMetaParser {

    public static TableMetaData parse(Class<?> clazz) {

        return TableMetaData.builder()
                .tableName(parseTableName(clazz))
                .entityClass(clazz)
                .fieldMap(parseFieldMap(clazz))
                .primaryKey(parsePrimaryKey(clazz))
                .build();
    }

    private static String parsePrimaryKey(Class<?> clazz) {
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(TableId.class)) {
                return field.getName();
            }
        }
        return null;
    }

    /**
     * 解析实体类的字段
     *
     * @param clazz 实体类
     * @return 字段映射
     */
    private static Map<String, Field> parseFieldMap(Class<?> clazz) {
        Field[] fields = clazz.getDeclaredFields();
        Map<String, Field> fieldMap = new HashMap<>();
        for (Field field : fields) {
            // 忽略合成字段
            if (field.isSynthetic()) {
                continue;
            }
            String columnName;
            // 带 TableField 注解的字段
            if (field.isAnnotationPresent(TableField.class)) {
                TableField tableField = field.getAnnotation(TableField.class);
                if (tableField.exclude()) {
                    continue;
                }
                columnName = StringUtils.isEmpty(tableField.value()) ? field.getName() : tableField.value();
            } else {
                columnName = field.getName();
            }
            fieldMap.put(columnName.toLowerCase(), field);
        }
        return fieldMap;
    }


    /**
     * 解释实体表的名称
     *
     * @param clazz 实体类
     * @return 表名称
     */
    private static String parseTableName(Class<?> clazz) {
        if (clazz.isAnnotationPresent(TableName.class)) {
            String tableName = clazz.getAnnotation(TableName.class).value();
            return StringUtils.isEmpty(tableName) ? clazz.getSimpleName() : tableName;
        }
        return clazz.getSimpleName();
    }
}
